﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;

namespace SongBuilder
{
	public class Note
	{
		private string note;
		private double noteValue;
		private int octave;

		public Note(string note, int octave)
		{
			this.note = note;
			this.octave = octave;
			this.noteValue = Note.FromString(note, octave);
		}

		public void Play(int duration)
		{
			if (this.noteValue == -1)
			{
				Thread.Sleep(duration);
			}
			else
			{
				Console.Beep(
					(int)Math.Round(this.noteValue, MidpointRounding.AwayFromZero),
					duration);
			}
		}

		public override string ToString()
		{
			return this.note + this.octave;
		}

		/// <summary>Factory method for generating notes by string value</summary>
		/// <remarks>
		/// Valid notes are "-" and "A"-"G". Use 'b' to indicate a flat note and
		/// '#' to indicate sharp notes. For example{ 'F#' or 'Cb'.        
		/// </remarks>
		public static double FromString(string note, int octave)
		{
			double octaveFrequency = Math.Pow(2, octave);
			switch (note)
			{
				case "C":
					return 16.35 * octaveFrequency;
				case "C#":
				case "Db":
					return 17.32 * octaveFrequency;
				case "D":
					return 18.35 * octaveFrequency;
				case "D#":
				case "Eb":
					return 19.45 * octaveFrequency;
				case "E":
					return 20.60 * octaveFrequency;
				case "F":
					return 21.83 * octaveFrequency;
				case "F#":
				case "Gb":
					return 23.12 * octaveFrequency;
				case "G":
					return 24.50 * octaveFrequency;
				case "G#":
				case "Ab":
					return 25.96 * octaveFrequency;
				case "A":
					return 27.50 * octaveFrequency;
				case "A#":
				case "Bb":
					return 29.14 * octaveFrequency;
				case "B":
					return 30.87 * octaveFrequency;
				case "-":
					return -1;
				default:
					throw new NotSupportedException();
			}
		}
	}
}